package corerun

import (
	"core/class"
	"core/coreentity"
	"core/coreservice"
	"core/coreutil"
	"core/datetime"
	"fmt"
	"gorm.io/gorm"
	"time"
)

type clsdb struct {
	Ldb     []coreentity.HtCls
	DB      *gorm.DB
	PrjName string
}

/**
*刷新entity到数据库
 */
func (p *clsdb) RefreshToDb() error {

	tx := p.DB.
		Model(&coreentity.HtCls{}).
		Unscoped().
		Where("prj_name=?", p.PrjName).
		Find(&(p.Ldb))
	if tx.Error != nil {
		return tx.Error
	}

	for _, mcls := range coreutil.StructUtil.GetAllEntity() {
		if mcls.PrjName != p.PrjName {
			continue
		}
		p.RefreshToDbCls(&mcls, "entity")
	}
	for _, mcls := range coreutil.StructUtil.GetAllDto() {
		if mcls.PrjName != p.PrjName {
			continue
		}
		p.RefreshToDbCls(&mcls, "dto")
	}

	for _, mcls := range coreutil.StructUtil.GetAllQto() {
		if mcls.PrjName != p.PrjName {
			continue
		}
		p.RefreshToDbCls(&mcls, "qto")
	}

	if tx.Error != nil {
		return tx.Error
	}
	return nil
}
func (p clsdb) FindFromDb(fullName string) *coreentity.HtCls {
	for _, v := range p.Ldb {
		if v.FullName == fullName {
			return &v
		}
	}
	return nil
}
func (p clsdb) RefreshToDbCls(mcls *class.MyClass, lx string) error {

	var mdb = p.FindFromDb(mcls.FullName)
	if mdb == nil {
		mdb = &coreentity.HtCls{
			Id:         coreutil.IdUtil.GetId(),
			PrjName:    mcls.PrjName,
			FullName:   mcls.FullName,
			Name:       mcls.Name,
			Memo:       mcls.Memo,
			BaseType:   lx,
			JsonFields: "",
			CrtDt:      datetime.MyTime(time.Now()),
			EdtDt:      datetime.MyTime(time.Now()),
			Deleted:    datetime.DeletedAt(0),
		}
		JsonFields, err := coreutil.Json.Marshal(mcls.Fileds)
		if err != nil {
			return err
		}
		mdb.JsonFields = JsonFields
		tx := coreservice.BaseService.Insert(mdb, p.DB)
		if tx.Error != nil {
			return tx.Error
		}
		var mcodelog = p.CreateHTCodeLogByDto(mdb)
		mcodelog.Memo = "新增"
		tx = coreservice.BaseService.Insert(mcodelog, p.DB)
		if tx.Error != nil {
			return tx.Error
		}
	} else {
		var msg = p.CompareCls(mcls, mdb, lx)
		if mdb.Deleted > 0 {
			mdb.Deleted = datetime.DeletedAt(0)
			msg = "删除恢复\r\n" + msg
		}
		if "" != msg {
			JsonFields, err := coreutil.Json.Marshal(mcls.Fileds)
			if err != nil {
				return err
			}
			mdb.JsonFields = JsonFields
			tx := p.DB.Unscoped()
			tx = coreservice.BaseService.UpdateByDto(mdb, &coreentity.HtCls{
				Id: mdb.Id,
			}, tx)
			if tx.Error != nil {
				return nil
			}
			var mcodelog = p.CreateHTCodeLogByDto(mdb)
			mcodelog.Memo = msg
			tx = coreservice.BaseService.Insert(mcodelog, p.DB)
			if tx.Error != nil {
				return tx.Error
			}
		}
	}
	return nil
}
func (p clsdb) CreateHTCodeLogByDto(mdb *coreentity.HtCls) *coreentity.HtCodeLog {
	var mcodelog = &coreentity.HtCodeLog{

		Id:       coreutil.IdUtil.GetId(),
		PrjName:  mdb.PrjName,
		Bid:      mdb.Id,
		Lx:       mdb.BaseType,
		FullName: mdb.FullName,
		Name:     mdb.Name,
		Memo:     "",
		CrtDt:    datetime.MyTime(time.Now()),
	}
	return mcodelog
}

/**
*比较类型 数据库差异
 */
func (p clsdb) CompareCls(mcls *class.MyClass, mdb *coreentity.HtCls, lx string) string {
	var sb = coreutil.MyStringBuilder{}
	if lx != mdb.BaseType {
		sb.Append("BaseType:").
			Append(mdb.BaseType).
			Append("=>").
			Append(lx).
			Append("\r\n")
		mdb.BaseType = lx
	}
	if mcls.Name != mdb.Name {
		sb.Append("Name:").
			Append(mdb.Name).
			Append("=>").
			Append(mcls.Name).
			Append("\r\n")
		mdb.Name = mcls.Name
	}

	if mcls.Memo != mdb.Memo {
		sb.Append("Memo:").
			Append(mdb.Memo).
			Append("=>").
			Append(mcls.Memo).
			Append("\r\n")
		mdb.Memo = mcls.Memo
	}

	var ldb []class.MyField
	coreutil.Json.Unmarshal(mdb.JsonFields, &ldb)

	for _, mf := range mcls.Fileds {
		var mfdb = p.FindField(mf.Ename, ldb)
		if mfdb == nil {
			sb.Append("字段:").
				Append(mf.Ename).
				Append(" 新增").
				Append("\r\n")
			continue
		}
		var sf = ""
		sf += p.CompareClsField(&mf, mfdb, "Name")
		sf += p.CompareClsField(&mf, mfdb, "Memo")
		sf += p.CompareClsField(&mf, mfdb, "Lx")
		sf += p.CompareClsField(&mf, mfdb, "List")
		sf += p.CompareClsField(&mf, mfdb, "Nullable")
		sf += p.CompareClsField(&mf, mfdb, "Str")
		sf += p.CompareClsField(&mf, mfdb, "Date")
		sf += p.CompareClsField(&mf, mfdb, "Num")
		sf += p.CompareClsField(&mf, mfdb, "Required")
		sf += p.CompareClsField(&mf, mfdb, "Regex")
		sf += p.CompareClsField(&mf, mfdb, "Vmin")
		sf += p.CompareClsField(&mf, mfdb, "Vmax")
		if "" != sf {
			sb.Append("字段:").
				Append(mf.Ename).
				Append(sf).
				Append("\r\n")

		}
	}

	//删除字段
	for _, mf := range ldb {
		var mfdb = p.FindField(mf.Ename, mcls.Fileds)
		if mfdb == nil {
			sb.Append("字段:").
				Append(mf.Ename).
				Append(" 删除").
				Append("\r\n")
			continue
		}
	}
	return sb.String()
}

/**
*查找filed
 */
func (p clsdb) FindField(Ename string, arr []class.MyField) *class.MyField {
	for _, v := range arr {
		if v.Ename == Ename {
			return &v
		}
	}
	return nil
}

/**
*比较字段
 */
func (p clsdb) CompareClsField(mf, mdb *class.MyField, fieldName string) string {
	var v = fmt.Sprintf("%v", coreutil.StructUtil.GetFieldValue(mf, fieldName))
	var dbv = fmt.Sprintf("%v", coreutil.StructUtil.GetFieldValue(mdb, fieldName))
	if v != dbv {
		return fieldName + " " + dbv + "=>" + v
	}
	return ""
}
